package no.awi.wpd.web.controller;

import java.io.IOException;
import java.io.Writer;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletResponse;

import no.awi.wpd.combat.model.ContactZone;
import no.awi.wpd.combat.model.Combat;
import no.awi.wpd.combat.model.CombatResult;
import no.awi.wpd.combat.service.CombatCalculatorService;
import no.awi.wpd.probability.WarhammerProbabilityFunctions;
import no.awi.wpd.unit.model.Profile;
import no.awi.wpd.unit.model.Unit;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.support.WebRequestDataBinder;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.servlet.ModelAndView;

@Controller
public class CombatController {

	private CombatCalculatorService combatCalculatorService;

	@Autowired
	public void setCombatCalculatorService(
			CombatCalculatorService combatCalculatorService) {
		this.combatCalculatorService = combatCalculatorService;
	}

	@RequestMapping("/combat.wpd")
	public ModelAndView setupForm() {

		ModelAndView model = new ModelAndView("combat");
		model.addObject(createCombat());
		return model;
	}

	@RequestMapping(method=RequestMethod.GET, value="/calculateCombat.wpd")
	public void calculateCombat(WebRequest request, HttpServletResponse response, Writer out)
			throws IOException {
		Combat combat = createCombat();
		WebRequestDataBinder dataBinder = new WebRequestDataBinder(combat);
		dataBinder.bind(request);
		Unit goodGuys = combat.getGoodGuys();
		combat.getGoodGuysContactZone().setModelsInBaseContact(goodGuys.getFileSize());
		Unit badGuys = combat.getBadGuys();
		combat.getBadGuysContactZone().setModelsInBaseContact(badGuys.getFileSize());
		
		response.setContentType("application/json");
		CombatResult combatResult = combatCalculatorService
				.calculateCombat(combat);
		double probabilityGoodGuysBreak = 1 - WarhammerProbabilityFunctions
				.getProbabilityPassLeadershipTest(combatResult.getResult(),
						goodGuys.getProfile().getLd(), goodGuys
								.isRerollBreakTest(), goodGuys.getProfile().isColdBlooded());
		double probabilityBadGuysBreak = 1 - WarhammerProbabilityFunctions
				.getProbabilityPassLeadershipTest(combatResult
						.getResult().negateAndReverse(), badGuys.getProfile().getLd(),
						badGuys.isRerollBreakTest(), badGuys.getProfile().isColdBlooded());
		Map<String, String> map = new HashMap<String, String>();
		map.put("combatResult", combatResult.getResult().toJson());
		map.put("probabilityBadGuysBreak", String
				.valueOf(probabilityBadGuysBreak));
		map.put("probabilityGoodGuysBreak", String
				.valueOf(probabilityGoodGuysBreak));
		map.put("goodGuysWoundsCaused", combat.getBadGuysContactZone()
				.getWoundsTaken().toJson());
		map.put("badGuysWoundsCaused", combat.getGoodGuysContactZone()
				.getWoundsTaken().toJson());
		out.write(toJson(map));
		out.flush();
	}

	private String toJson(Map<String, String> map) {
		StringBuffer json = new StringBuffer("{");
		for (String name : map.keySet()) {
			json.append(name + ": " + map.get(name));
			json.append(", ");
		}
		return json.substring(0, json.length() - 2) + "}";
	}

	private Combat createCombat() {
		Combat combat = new Combat();

		Unit goodGuys = new Unit();
		goodGuys.setProfile(new Profile());
		goodGuys.setMount(new Profile());
		goodGuys.getMount().at(0);
		combat.setGoodGuys(goodGuys);

		Unit badGuys = new Unit();
		badGuys.setProfile(new Profile());
		badGuys.setMount(new Profile());
		badGuys.getMount().at(0);
		combat.setBadGuys(badGuys);

		combat.setChargers(goodGuys);

		ContactZone ggaz = new ContactZone();
		ggaz.setModelsInBaseContact(combat.getGoodGuys().getFileSize());
		ggaz.setUnit(combat.getGoodGuys());

		ContactZone bgaz = new ContactZone();
		bgaz.setModelsInBaseContact(combat.getBadGuys().getFileSize());
		bgaz.setUnit(combat.getBadGuys());

        ggaz.setAttackableOpponent(bgaz);
        bgaz.setAttackableOpponent(ggaz);

        combat.setGoodGuysContactZone(ggaz);
		combat.setBadGuysContactZone(bgaz);

		return combat;
	}

}
